package org.dftproject.genesis.core.data.flow;

import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class Collector<T> {

	private boolean canceled = false;
	private final Set<T> elements = Collections.synchronizedSet(new HashSet<T>());
	private final Set<String> providerNames = Collections.synchronizedSet(new HashSet<String>());
	private final Set<ICollectorListener<T>> listeners = Collections.synchronizedSet(new HashSet<ICollectorListener<T>>());
	
	public void addElement(T element) {
		synchronized (elements) {
			if (elements.contains(element))
				return;
			elements.add(element);
		}
			
		synchronized (listeners) {
			Iterator<ICollectorListener<T>> iter = listeners.iterator();
			while (iter.hasNext()) {
				try {
					iter.next().elementAdded(this, element);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	public void setProviderStatus(String providerName, boolean active) {
		synchronized (providerNames) {
			if (active)
				providerNames.add(providerName);
			else
				providerNames.remove(providerName);
		}
		
		synchronized (listeners) {
			Iterator<ICollectorListener<T>> iter = listeners.iterator();
			while (iter.hasNext()) {
				try {
					iter.next().providerStatusChanged(this, providerName, active);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public void cancel() {
		canceled = true;
	}
	
	public boolean isCanceled() {
		return canceled;
	}
	
	public Object[] getElements() {
		return elements.toArray();
	}
	
	public T[] getElements(T[] a) {
		return elements.toArray(a);
	}
	
	public String[] getActiveProviderNames() {
		return providerNames.toArray(new String[0]);
	}

	public boolean isActive() {
		return !canceled && !providerNames.isEmpty();
	}
	
	public void addListener(ICollectorListener<T> listener) {
		listeners.add(listener);
	}

	public void removeListener(ICollectorListener<T> listener) {
		listeners.remove(listener);
	}

}
